package org.convallaria.framework.security.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.convallaria.framework.security.annotation.RequiresPermissions;
import org.convallaria.framework.security.annotation.RequiresRoles;
import org.convallaria.framework.security.core.SecurityUser;
import org.convallaria.framework.security.util.SecurityUtils;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Set;

/**
 * 权限切面
 * 处理自定义权限注解
 * 
 * @author convallaria
 * @since 1.0.0
 */
@Slf4j
@Aspect
@Component
public class PermissionAspect {

    @Around("@annotation(requiresPermissions)")
    public Object checkPermissions(ProceedingJoinPoint joinPoint, RequiresPermissions requiresPermissions) throws Throwable {
        SecurityUser user = SecurityUtils.getCurrentUser();
        if (user == null) {
            throw new AccessDeniedException("用户未登录");
        }

        String[] requiredPermissions = requiresPermissions.value();
        Set<String> userPermissions = user.getPermissions();

        boolean hasPermission = checkLogical(requiredPermissions, userPermissions, 
                requiresPermissions.logical() == RequiresPermissions.Logical.AND);

        if (!hasPermission) {
            log.warn("用户 {} 缺少权限: {}", user.getUsername(), Arrays.toString(requiredPermissions));
            throw new AccessDeniedException("权限不足");
        }

        return joinPoint.proceed();
    }

    @Around("@annotation(requiresRoles)")
    public Object checkRoles(ProceedingJoinPoint joinPoint, RequiresRoles requiresRoles) throws Throwable {
        SecurityUser user = SecurityUtils.getCurrentUser();
        if (user == null) {
            throw new AccessDeniedException("用户未登录");
        }

        String[] requiredRoles = requiresRoles.value();
        Set<String> userRoles = user.getRoles();

        boolean hasRole = checkLogical(requiredRoles, userRoles, 
                requiresRoles.logical() == RequiresRoles.Logical.AND);

        if (!hasRole) {
            log.warn("用户 {} 缺少角色: {}", user.getUsername(), Arrays.toString(requiredRoles));
            throw new AccessDeniedException("权限不足");
        }

        return joinPoint.proceed();
    }

    /**
     * 检查权限/角色逻辑
     * 
     * @param required 需要的权限/角色
     * @param userSet 用户拥有的权限/角色
     * @param isAnd 是否是AND逻辑
     * @return 是否满足条件
     */
    private boolean checkLogical(String[] required, Set<String> userSet, boolean isAnd) {
        if (required == null || required.length == 0) {
            return true;
        }

        if (userSet == null || userSet.isEmpty()) {
            return false;
        }

        if (isAnd) {
            // AND逻辑：必须拥有所有权限/角色
            return userSet.containsAll(Arrays.asList(required));
        } else {
            // OR逻辑：只需拥有其中一个权限/角色
            return Arrays.stream(required).anyMatch(userSet::contains);
        }
    }
}
